package com.example.shuiyin.exception;

import com.example.shuiyin.dto.ApiResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;

import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ApiResponse<?>> handleAccessDeniedException(AccessDeniedException ex) {
        log.error("访问被拒绝: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.FORBIDDEN, ex.getMessage());
    }

    @ExceptionHandler(AuthenticationException.class)
    public ResponseEntity<ApiResponse<?>> handleAuthenticationException(AuthenticationException ex) {
        log.error("认证失败: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.UNAUTHORIZED, ex.getMessage());
    }
    
    @ExceptionHandler(AppException.class)
    public ResponseEntity<ApiResponse<Void>> handleAppException(AppException e, HttpServletRequest request) {
        log.error("应用异常: {}, URL: {}", e.getMessage(), request.getRequestURL(), e);
        
        // 用户相关错误 (1000-1999)
        if (e.getMessage().contains("邮箱已存在")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(1001, "邮箱已被使用"));
        } else if (e.getMessage().contains("用户名已存在")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(1002, "用户名已存在"));
        } else if (e.getMessage().contains("手机号已被使用")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(1003, "手机号已被使用"));
        } else if (e.getMessage().contains("原密码不正确")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(1004, "原密码不正确"));
        } else if (e.getMessage().contains("重置令牌已过期") || e.getMessage().contains("无效的重置令牌")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(1005, "重置链接无效或已过期"));
        } else if (e.getMessage().contains("用户不存在")) {
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND)
                    .body(ApiResponse.error(1006, "用户不存在"));
        } else if (e.getMessage().contains("密码错误") || e.getMessage().contains("用户名或密码错误")) {
            return ResponseEntity
                    .status(HttpStatus.UNAUTHORIZED)
                    .body(ApiResponse.error(1007, "用户名或密码错误"));
        } else if (e.getMessage().contains("账号已禁用") || e.getMessage().contains("账号状态异常")) {
            return ResponseEntity
                    .status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(1008, "账号状态异常，请联系管理员"));
        }
        
        // 文件相关错误 (2000-2999)
        else if (e.getMessage().contains("文件不存在")) {
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND)
                    .body(ApiResponse.error(2001, "文件不存在"));
        } else if (e.getMessage().contains("文件上传失败")) {
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error(2002, "文件上传失败，请稍后重试"));
        } else if (e.getMessage().contains("文件类型不支持") || e.getMessage().contains("不支持的文件类型")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(2003, "不支持的文件类型"));
        } else if (e.getMessage().contains("文件大小超过限制") || e.getMessage().contains("文件太大")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(2004, "文件大小超过限制"));
        } else if (e.getMessage().contains("存储空间不足")) {
            return ResponseEntity
                    .status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(2005, "存储空间不足，请升级套餐或清理空间"));
        }
        
        // 媒体处理相关错误 (3000-3999)
        else if (e.getMessage().contains("水印处理失败")) {
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error(3001, "水印处理失败，请稍后重试"));
        } else if (e.getMessage().contains("不支持的媒体类型") || e.getMessage().contains("媒体类型不支持")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(3002, "不支持的媒体类型"));
        } else if (e.getMessage().contains("视频处理失败")) {
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error(3003, "视频处理失败，请稍后重试"));
        } else if (e.getMessage().contains("处理配额不足")) {
            return ResponseEntity
                    .status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(3004, "处理配额不足，请升级套餐"));
        }
        
        // 权限相关错误 (4000-4999)
        else if (e.getMessage().contains("无权访问") || e.getMessage().contains("没有权限")) {
            return ResponseEntity
                    .status(HttpStatus.FORBIDDEN)
                    .body(ApiResponse.error(4001, "没有权限执行此操作"));
        } else if (e.getMessage().contains("未登录") || e.getMessage().contains("token无效") || e.getMessage().contains("token已过期")) {
            return ResponseEntity
                    .status(HttpStatus.UNAUTHORIZED)
                    .body(ApiResponse.error(4002, "未登录或登录已过期，请重新登录"));
        } else if (e.getMessage().contains("请求频率过高")) {
            return ResponseEntity
                    .status(HttpStatus.TOO_MANY_REQUESTS)
                    .body(ApiResponse.error(4003, "请求频率过高，请稍后再试"));
        }
        
        // 支付相关错误 (5000-5999)
        else if (e.getMessage().contains("支付失败")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(5001, "支付失败，请稍后重试"));
        } else if (e.getMessage().contains("订单不存在")) {
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND)
                    .body(ApiResponse.error(5002, "订单不存在"));
        } else if (e.getMessage().contains("订单已支付")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(5003, "订单已支付，请勿重复支付"));
        } else if (e.getMessage().contains("订单已取消")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(5004, "订单已取消"));
        } else if (e.getMessage().contains("套餐不存在")) {
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND)
                    .body(ApiResponse.error(5005, "套餐不存在"));
        } else if (e.getMessage().contains("库存不足")) {
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(ApiResponse.error(5006, "库存不足"));
        }
        
        // 系统错误 (9000-9999)
        else if (e.getMessage().contains("系统维护中")) {
            return ResponseEntity
                    .status(HttpStatus.SERVICE_UNAVAILABLE)
                    .body(ApiResponse.error(9001, "系统维护中，请稍后再试"));
        } else if (e.getMessage().contains("服务不可用")) {
            return ResponseEntity
                    .status(HttpStatus.SERVICE_UNAVAILABLE)
                    .body(ApiResponse.error(9002, "服务暂时不可用，请稍后再试"));
        } else if (e.getMessage().contains("系统繁忙")) {
            return ResponseEntity
                    .status(HttpStatus.SERVICE_UNAVAILABLE)
                    .body(ApiResponse.error(9003, "系统繁忙，请稍后再试"));
        }
        
        // 默认处理方式 - 使用异常中的错误码和消息
        return ResponseEntity
                .status(e.getHttpStatus() != null ? e.getHttpStatus() : HttpStatus.BAD_REQUEST)
                .body(ApiResponse.error(e.getCode(), e.getMessage()));
    }
    
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<ApiResponse<?>> handleNoHandlerFoundException(NoHandlerFoundException ex) {
        log.error("找不到资源: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.RESOURCE_NOT_FOUND, ex.getRequestURL());
    }
    
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public ResponseEntity<ApiResponse<List<String>>> handleValidationExceptions(Exception ex, HttpServletRequest request) {
        log.error("参数验证失败: {}, URL: {}", ex.getMessage(), request.getRequestURL(), ex);
        
        List<String> errors = new ArrayList<>();
        BindingResult bindingResult = null;
        
        if (ex instanceof MethodArgumentNotValidException) {
            bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
        } else if (ex instanceof BindException) {
            bindingResult = ((BindException) ex).getBindingResult();
        }
        
        if (bindingResult != null) {
            for (FieldError error : bindingResult.getFieldErrors()) {
                errors.add(error.getField() + ": " + error.getDefaultMessage());
            }
        }
        
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(ApiResponse.error(ErrorCode.INVALID_PARAMETER.getCode(), "参数验证失败", errors));
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<ApiResponse<Void>> handleMaxUploadSizeExceededException(
            MaxUploadSizeExceededException e, HttpServletRequest request) {
        log.error("文件大小超出限制: {}, URL: {}", e.getMessage(), request.getRequestURL(), e);
        
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(ApiResponse.error(ErrorCode.FILE_TOO_LARGE.getCode(), "上传文件大小超出限制"));
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResponseEntity<ApiResponse<?>> handleDataIntegrityViolationException(DataIntegrityViolationException ex) {
        log.error("数据完整性违规: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.INVALID_PARAMETER, "数据操作失败，请检查输入数据");
    }

    @ExceptionHandler(EmptyResultDataAccessException.class)
    public ResponseEntity<ApiResponse<?>> handleEmptyResultDataAccessException(EmptyResultDataAccessException ex) {
        log.error("未找到数据: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.RESOURCE_NOT_FOUND, "未找到相关数据");
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<ApiResponse<?>> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.error("请求数据格式错误: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.INVALID_PARAMETER, "请求数据格式错误");
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<ApiResponse<?>> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) {
        log.error("不支持的请求方法: {}", ex.getMessage());
        return buildErrorResponse(ErrorCode.INVALID_PARAMETER, "不支持的请求方法: " + ex.getMessage());
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<Void>> handleException(Exception e, HttpServletRequest request) {
        log.error("系统异常: {}, URL: {}", e.getMessage(), request.getRequestURL(), e);
        
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error(ErrorCode.INTERNAL_ERROR.getCode(), "系统内部错误"));
    }
    
    /**
     * 构建错误响应
     */
    private ResponseEntity<ApiResponse<?>> buildErrorResponse(ErrorCode errorCode, Object... args) {
        String message = errorCode.getMessage();
        if (args != null && args.length > 0) {
            message = errorCode.formatMessage(args);
        }
        return ResponseEntity.status(errorCode.getHttpStatus())
                .body(ApiResponse.error(message, errorCode.getCode()));
    }
} 